package cn.com.system.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.com.system.entity.SysDept;
import cn.com.system.entity.SysLog;
import cn.com.system.entity.SysRole;
import cn.com.system.entity.SysUser;
import cn.com.system.entity.SysUserIdentityEntity;
import cn.com.common.constants.Constants;
import cn.com.common.exception.BusinessException;
import cn.com.common.exception.code.BaseResponseCode;

import cn.com.gt3.mapper.DmQxSwrysfMapper;
import cn.com.gt3.service.DmGySwjgService;
import cn.com.gt3.service.DmQxSwrysfService;
import cn.com.system.mapper.SysDeptMapper;
import cn.com.system.mapper.SysUserIdentityMapper;
import cn.com.system.mapper.SysUserMapper;
import cn.com.system.service.LogService;
import cn.com.system.service.PermissionService;
import cn.com.system.service.RoleService;
import cn.com.system.service.SysLoginIdentityService;
import cn.com.system.service.SysUserIdentityService;
import cn.com.system.service.UserRoleService;
import cn.com.system.service.UserService;
import cn.com.system.vo.req.UserRoleOperationReqVO;
import cn.com.system.vo.res.LoginRespVO;
import cn.com.system.vo.res.UserOwnRoleRespVO;
import cn.com.util.PasswordUtils;
import cn.com.util.TsBqUtils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.util.Date;
import java.util.List;

/**
 * 用户 服务类
 *
 * @author wenbin
 * @version V1.0
 * @date 2020年3月18日
 */
@Service
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements UserService {

	@Resource
	private SysUserMapper sysUserMapper;
	@Resource
	private RoleService roleService;
	@Resource
	private PermissionService permissionService;
	@Resource
	private UserRoleService userRoleService;
	@Resource
	private SysDeptMapper sysDeptMapper;
	@Resource
	private DmQxSwrysfMapper dmQxSwrysfMapper;
	@Resource
	private DmQxSwrysfService dmQxSwrysfService;
	@Resource
	private SysUserIdentityService sysUserIdentityService;
	@Resource
	private DmGySwjgService dmGySwjgService;
	@Resource
	private HttpSessionService httpSessionService;
	@Resource
	private SysLoginIdentityService sysLoginIdentityService;
	@Resource
	private LogService logService;
	
	@Resource
	private SysUserIdentityMapper sysUserIdentityMapper;
	
	
	@Value("${spring.redisToken.allowMultipleLogin}")
	private Boolean allowMultipleLogin;

	@Override
	public void register(SysUser sysUser) {
		SysUser sysUserOne = sysUserMapper
				.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, sysUser.getUsername()));
		if (sysUserOne != null) {
			throw new BusinessException("用户名已存在！");
		}
		sysUser.setSalt(PasswordUtils.getSalt());
		String encode = PasswordUtils.encode(sysUser.getPassword(), sysUser.getSalt());
		sysUser.setPassword(encode);
		sysUserMapper.insert(sysUser);
	}

	@Override
	public LoginRespVO login(SysUser vo, HttpServletRequest request) {
		SysUser sysUser = sysUserMapper
				.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
		if (null == sysUser) {
			throw new BusinessException(BaseResponseCode.NOT_ACCOUNT);
		}
		if (sysUser.getStatus() == 2) {
			throw new BusinessException(BaseResponseCode.USER_LOCK);
		}
		if (!PasswordUtils.matches(sysUser.getSalt(), vo.getPassword(), sysUser.getPassword())) {

			// TODO 用户锁定，当密码输入一定次数后自动锁定账户。 5次
			HttpSession session = request.getSession();
			Object attribute = session.getAttribute("USERLOCK");
			if (attribute == null) {
				request.getSession().setAttribute("USERLOCK", "1");
			} else {
				int i = Integer.parseInt(session.getAttribute("USERLOCK").toString());
				// 输入错误密码的次数
				if (i == 5) {
					Date date = new Date();
					sysUser.setStatus(2);
					sysUser.setUpdateTime(date);
					sysUserMapper.updateById(sysUser);
				} else {
					i++;
					request.getSession().setAttribute("USERLOCK", i);
				}
			}

			throw new BusinessException(BaseResponseCode.PASSWORD_ERROR);

		}
		
		// edit 增加对身份的处理
		// List<DmQxSwrysfEntity> dmQxSwrysfList = dmQxSwrysfService.getUserIdentityById(sysUser.getId());
		List<SysUserIdentityEntity> sysUserIdentityList = sysUserIdentityService.getUserIdentityById(sysUser.getId());
		
		
		if (TsBqUtils.isNull(sysUserIdentityList)) {
			throw new BusinessException(BaseResponseCode.IDENTITY_ERROR);
		}
		
		SysUserIdentityEntity sysUserIdentityEntity = sysUserIdentityList.get(0);

		sysUser.setDeptId(sysUserIdentityEntity.getDeptId());
		sysUser.setDeptNo(sysUserIdentityEntity.getDeptId());

		sysUser.setIdentityName(sysUserIdentityEntity.getName());
		
		String identityId = sysUserIdentityEntity.getId();
		
		sysUser.setIdentityId(identityId);

		LoginRespVO respVO = new LoginRespVO();
		BeanUtils.copyProperties(sysUser, respVO);
		respVO.setIdentityTaxorgCode(sysUserIdentityEntity.getDeptId());
		// 是否删除之前token， 此处控制是否支持多登陆端；
		// true:允许多处登陆; false:只能单处登陆，顶掉之前登陆
		if (!allowMultipleLogin) {
			httpSessionService.abortUserById(sysUser.getId());
		}

		String token = httpSessionService.createTokenAndUser(sysUser, roleService.getRoleNames(identityId),
				roleService.getRoleIds(identityId), permissionService.getPermissionsByUserId(identityId));
		respVO.setAccessToken(token);
		// 记录登录
		SysLog sysLog = new SysLog();
		
		sysLog.setUserId(sysUser.getUsername());
		sysLog.setUsername(sysUser.getUsername());
		sysLog.setOperation("用户登录");
		// sysLog.setTime("");
		sysLog.setMethod("cn.com.system.service.impl.UserServiceImpl.login");
		sysLog.setParams("");
		sysLog.setIp("");
		sysLog.setTaxorgcode(sysUser.getDeptId());
		sysLog.setCreateTime(new Date());
		
		logService.save(sysLog);
		return respVO;
		
	}

	@Override
	public void updateUserInfo(SysUser vo) {

		SysUser sysUser = sysUserMapper.selectById(vo.getId());
		if (null == sysUser) {
			throw new BusinessException(BaseResponseCode.DATA_ERROR);
		}

		// 如果用户名变更
		if (!sysUser.getUsername().equals(vo.getUsername())) {
			SysUser sysUserOne = sysUserMapper
					.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
			if (sysUserOne != null) {
				throw new BusinessException("用户名已存在！");
			}
		}

		// 如果用户名、密码、状态 变更，删除redis中用户绑定的角色跟权限
		if (!sysUser.getUsername().equals(vo.getUsername())
				|| (!StringUtils.isEmpty(vo.getPassword())
						&& !sysUser.getPassword().equals(PasswordUtils.encode(vo.getPassword(), sysUser.getSalt())))
				|| !sysUser.getStatus().equals(vo.getStatus())) {
			// httpSessionService.abortUserById(vo.getId());
		}

		if (!StringUtils.isEmpty(vo.getPassword())) {
			String newPassword = PasswordUtils.encode(vo.getPassword(), sysUser.getSalt());
			vo.setPassword(newPassword);
		} else {
			vo.setPassword(null);
		}
		
		// 不允许用户名变更
		vo.setUsername(sysUser.getUsername());
		vo.setUpdateId(httpSessionService.getCurrentUserId());
		sysUserMapper.updateById(vo);
		
		LambdaQueryWrapper<SysUserIdentityEntity> queryWrapper = Wrappers.lambdaQuery();

		queryWrapper.eq(SysUserIdentityEntity::getUserId, vo.getId());
		
		List<SysUserIdentityEntity> userIdentityList = sysUserIdentityMapper.selectList(queryWrapper);
		for (SysUserIdentityEntity sysUserIdentity : userIdentityList) {
			sysUserIdentity.setDeptId(vo.getDeptId());
			sysUserIdentity.setUpdateId(httpSessionService.getCurrentUserId());
			sysUserIdentity.setUpdateTime(vo.getUpdateTime());
			sysUserIdentityMapper.updateById(sysUserIdentity);
			
		}
		
	}

	@Override
	public void updateUserInfoMy(SysUser vo) {

		SysUser user = sysUserMapper.selectById(httpSessionService.getCurrentUserId());
		if (null == user) {
			throw new BusinessException(BaseResponseCode.DATA_ERROR);
		}
		if (!StringUtils.isEmpty(vo.getPassword())) {
			String newPassword = PasswordUtils.encode(vo.getPassword(), user.getSalt());
			vo.setPassword(newPassword);
		} else {
			vo.setPassword(null);
		}
		vo.setUpdateId(httpSessionService.getCurrentUserId());
		sysUserMapper.updateById(vo);

	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public IPage<SysUserIdentityEntity> pageInfo(SysUser vo) {
		String currentDeptId = httpSessionService.getCurrentDeptId();

		String deptNo = vo.getDeptNo();
		String username = vo.getUsername();

		String nickName = vo.getNickName();

		String deptId = "";
		if (!TsBqUtils.isNull(deptNo)) {
			deptId = deptNo;
		} else {
			// DmGySwjgEntity dmGySwjgEntity = dmGySwjgService.getById(currentDeptId);
			SysDept sysDept = sysDeptMapper.selectById(currentDeptId);
			deptId = sysDept.getId();
		}
		
		/*List<DmGySwjgEntity> dmGySwjgEntityList = TsBqUtils.recursionLevelTaxOrg(deptId);
		List<String> taxOrglist = new ArrayList<String>();
		taxOrglist.add(deptId);
		if (!TsBqUtils.isNull(dmGySwjgEntityList)) {
			for (DmGySwjgEntity dmGySwjg : dmGySwjgEntityList) {
				String swjgDm = dmGySwjg.getSwjgDm();
				taxOrglist.add(swjgDm);
			}
		}*/

		Page page = new Page(vo.getPage(), vo.getLimit());
		LambdaQueryWrapper<SysUserIdentityEntity> queryWrapper = Wrappers.lambdaQuery();

		if (!TsBqUtils.isNull(username)) {
			queryWrapper.like(SysUserIdentityEntity::getUserId, username);
		}

		if (!TsBqUtils.isNull(nickName)) {
			queryWrapper.like(SysUserIdentityEntity::getName, nickName);
		}

		queryWrapper.eq(SysUserIdentityEntity::getDeptId, deptId);
		
		// IPage<DmQxSwrysfEntity> iPage = dmQxSwrysfMapper.selectPage(page, queryWrapper);
		
		IPage<SysUserIdentityEntity> iPage = sysUserIdentityService.page(page, queryWrapper);
		
		return iPage;
	}
	
	@Override
	@DS("master")
	public SysUser getUser(String id) {
		SysUser sysUser = this.getById(id);
		return sysUser;
		
	}
	
	@Override
	public void addUser(SysUser vo) {
		
		SysUser sysUserOne = sysUserMapper
				.selectOne(Wrappers.<SysUser>lambdaQuery()
						.eq(SysUser::getUsername, vo.getUsername())
						.eq(SysUser::getId, vo.getUsername()));
		
		if (sysUserOne != null) {
			throw new BusinessException("用户已存在，请勿重复添加！");
		}
		
		vo.setRealName(vo.getUsername());
		vo.setNickName(vo.getUsername());
		
		vo.setSalt(PasswordUtils.getSalt());
		String encode = PasswordUtils.encode(vo.getPassword(), vo.getSalt());
		vo.setId(vo.getUsername());
		vo.setPassword(encode);
		vo.setStatus(1);
		vo.setCreateWhere(1);
		sysUserMapper.insert(vo);
		
		if (null != vo.getRoleIds() && !vo.getRoleIds().isEmpty()) {
			UserRoleOperationReqVO reqVO = new UserRoleOperationReqVO();
			reqVO.setUserId(vo.getId());
			reqVO.setRoleIds(vo.getRoleIds());
			userRoleService.addUserRoleInfo(reqVO);
		}
		
		// 写入 sys_user_identity 
		SysUserIdentityEntity sysUserIdentity = new SysUserIdentityEntity();
		sysUserIdentity.setId(vo.getUsername() + "01");
		sysUserIdentity.setName(vo.getUsername());
		sysUserIdentity.setUserId(vo.getId());
		sysUserIdentity.setDeptId(vo.getDeptId());
		sysUserIdentity.setMainFlag("Y");
		sysUserIdentity.setSerial("1");
		sysUserIdentity.setStatus(1);
		sysUserIdentity.setDeleted(Constants.DATA_NOT_DELETED);
		sysUserIdentity.setCreateId(vo.getCreateId());
		sysUserIdentity.setCreateTime(vo.getCreateTime());

		
		sysUserIdentityMapper.insert(sysUserIdentity);
		
	}

	@Override
	public void updatePwd(SysUser vo) {

		SysUser sysUser = sysUserMapper.selectById(vo.getId());
		if (sysUser == null) {
			throw new BusinessException(BaseResponseCode.DATA_ERROR);
		}

		if (!PasswordUtils.matches(sysUser.getSalt(), vo.getOldPwd(), sysUser.getPassword())) {
			throw new BusinessException(BaseResponseCode.OLD_PASSWORD_ERROR);
		}
		if (sysUser.getPassword().equals(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()))) {
			throw new BusinessException("新密码不能与旧密码相同");
		}
		sysUser.setPassword(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()));
		sysUserMapper.updateById(sysUser);
		httpSessionService.abortAllUserByToken();

	}

	@Override
	public UserOwnRoleRespVO getUserOwnRole(String userId) {
		List<String> roleIdsByUserId = userRoleService.getRoleIdsByUserId(userId);
		List<SysRole> list = roleService.list();
		UserOwnRoleRespVO vo = new UserOwnRoleRespVO();
		vo.setAllRole(list);
		vo.setOwnRoles(roleIdsByUserId);
		return vo;
	}

	@Override
	public void forgetPwd(SysUser vo) {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateUserUnlock(SysUser sysUser) {
		// TODO Auto-generated method stub

	}

}
